package character {
	import org.flixel.plugin.photonstorm.FlxVelocity;
	import org.flixel.FlxPoint;
	import states.GamePlayState;
	import org.flixel.FlxG;
	import events.GameEvent;
	import events.GameEventManager;
	import org.flixel.FlxObject;
	import org.flixel.FlxSprite;
	/**
	 * @author NilsIH
	 */
	public class Monster extends NiloGroup{
		
		[Embed(source="../img/monster.png")] private var MonsterGFX : Class;
		[Embed(source="../img/monster_gul.png")] private var MonsterYellow : Class;
		[Embed(source="../img/planten.png")] private var Plant : Class;
		[Embed(source="../img/planten_gul.png")] private var PlantYellow : Class;
		
		private var _monster:FlxSprite;
		private var _plant:FlxSprite;
		private var _gameEvents:GameEventManager;
		private var _gameEvent:GameEvent;
		
		private var _plantCollider:Collider;
		private var _monsterCollider:Collider;
		private var _monsterRangeCollider:Collider;
		private var _cooldown:Number = 3;
		
		private var _direction:FlxPoint = new FlxPoint();
		public var speed:Number = 40;
		
		public var evolutionCountdown:Number = 20;
		public var evolutionCountdownDeviation:Number = 10;
		
		private var _level:uint;
		private var _niloTile:NiloTile;
		private var _monsterType:String;
		private var _humanBeingEaten:Human;
		private var _humansDevoured:uint;
		private var _ready:Boolean;
		
		private var _timeRemaining:Number = 0;
		
		public var timeUntilDirChange:Number = 7;
		
		public function Monster(niloTile:NiloTile){
			x = niloTile.x;
			y = niloTile.y;
			_monster = new FlxSprite(-21, -135);
			
			_monster.loadGraphic(MonsterGFX, true, false, 96, 192);
			_monster.addAnimation("spawn", [0, 1, 2], 8, false);
			_monster.addAnimation("walk", [2, 3, 4, 5], 8);
			_monster.addAnimation("shooting", [6, 7, 8], 8);
			_monster.addAnimation("death", [9, 10, 11, 12, 13], 9, false);
			_monster.addAnimationCallback(acb);
			
			_plant = new FlxSprite(0, -50);
			_plant.loadGraphic(Plant, true, false, 72, 104);
			_plant.addAnimation("spawn", [0, 1, 2, 4, 5, 6, 7], 8, false);
			_plant.addAnimation("idle", [7]);
			_plant.addAnimation("eating", [7, 6, 5, 4, 3, 3, 3, 3, 5, 8, 9, 10, 11, 12, 13, 14, 13, 12, 7, 6, 5, 4, 3, 4, 5, 6, 7], 11, false);
			_plant.addAnimation("death", [7, 6, 5, 4, 3, 2, 1, 0], 8, false);
			_plant.addAnimationCallback(acbPlant);
			
			_gameEvents = new GameEventManager();
			_gameEvents.add(_gameEvent);
			_level = 1;
			_niloTile = niloTile;
			add(_gameEvents);
			
			_plant.play("spawn");
			add(_plant);
			
			_ready = false;
			_humansDevoured = 0;
			_cooldown = 0;
			
			
		}
		
		public function acb(name:String, frameN:uint, frameI:uint):void {
			if (name == "spawn"){
				if (frameN == 2){
					_ready = true;
					changeDirection();
					_monster.play("walk");
				}
			}
			else if (name == "death"){
				if (frameN == 2){
					kill();
					GamePlayState.monsters.remove(this);
				}
			}
		}
		
		public function acbPlant(name:String, frameN:uint, frameI:uint):void {
			if (name == "spawn"){
				if (frameI == 7){
					_ready = true;
					FlxG.play(AssetStore.mons2);
				}
			}
			else if (name == "eating"){
				if (frameN == 23){
					_humansDevoured++;
					_humanBeingEaten = null;
					_cooldown = 3;
					if (_humansDevoured >= 10){
						this.evolveToMonster();
					}
				}
			}
			else if (name == "death"){
				if (frameN == 7){
					kill();
					GamePlayState.monsters.remove(this);
				}
				
			}
		}
		
		override public function update():void {
			super.update();
			if (_ready && _level == 2){
				_timeRemaining -= FlxG.elapsed;
				if (_timeRemaining <= 0){
					changeDirection();
				}
			}
			if (_cooldown > 0){
				_cooldown -= FlxG.elapsed;
			}
		}
		
		public function evolveToMonster():void{
			_level++;
			if (_level == 2){
				_ready = false;
				remove(_plant);
				_monster.play("spawn");
				add(_monster);	
				FlxG.play(AssetStore.mons1);
			}
		}
		
		public function changeDirection():void {
			if (alive)
			{
				var x:Number = (FlxG.random() * 2) - 1;
				var y:Number = (FlxG.random() * 2) - 1;
				var sum:Number = Math.abs(x) + Math.abs(y);
				_direction.x = x / sum;
				_direction.y = y / sum;
				
				
				if (NiloUtils.numberIsOver(.3)){
					moveTowardsHospital();
				}
				else {
					velocity.x = _direction.x * speed;
					velocity.y = _direction.y * speed;
				}
				
				_timeRemaining = timeUntilDirChange;
			}
		}
		
		public function moveTowardsHospital():void {
			FlxVelocity.moveTowardsPoint(_refobj, GamePlayState.hospital.closestEntrance(_refobj), speed);
		}
		
		public function perish():void {
			_ready = false;
			if (_level == 1){
				_plant.play("death");
			}
			else {
				_monster.play("death");
			}
		}
		
		override protected function setupColliders():void {
			_plantCollider = new Collider(-25, -25, 110, 110);
			//_plantCollider.visible = true;
			_plantCollider.uniqueID = "monster";
			
			_monsterCollider = new Collider(-10, -35, 70, 90);
			//_monsterCollider.visible = true;
			_monsterCollider.uniqueID = "monster";
			//_monsterRangeCollider = new Collider(-15, -15, 100, 100);
			addCollider(_plantCollider);
			addCollider(_monsterCollider);
		}
		
		override public function collided(ownCollider:Collider, object:FlxObject):void {
			if (_ready && ownCollider == _plantCollider && _cooldown <= 0){
				//	Eat:
				if (object is Human){
					if (_humanBeingEaten == null){
						var human:Human = object as Human;
						if (!human.isInjured){
							_humanBeingEaten = human;
							human.eat();
							_plant.play("eating");
						}
					}
				}
				else if (object is Car){
					var car:Car = object as Car;
					car.crash();
				}
				
			}
			else if (ownCollider == _monsterCollider){
				//	Do something smart
				if (object is Human){
					(object as Human).runOver();
				}
				else if (object is Car){
					(object as Car).crash();
				}
				
			}
		}
		
		override public function colliderOutOfBounds(ownCollider:Collider):void{
			kill();
			GamePlayState.monsters.remove(this);
		}
		
	}
}
